﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;
using KrisThom.Execute;
using KrisThom.Hash;

namespace Mole
{
    [Serializable]
    public class UrlProcessing
    {
        private Object thisLock = new Object();
        
        private uint _siteId = 0;
        private String _appDir = System.Windows.Forms.Application.StartupPath;
        private String _projectName;
        private String _url;
        private String _outputfilepath;
        private Double _msRuntime = 60000;
        private DateTime _StartTime;
        private DateTime _EndTime;
        private UrlProcessed _urlProcessed;
        private List<DirectoryList> _filesProcessed = new List<DirectoryList>();

        public uint SiteId
        {
            get { return _siteId; }
            set { _siteId = value; }
        }
        public String ApplicationDirectory
        {
            get { return _appDir; }
            set { _appDir = value; }
        }
        public String ProjectName
        {
            get { return _projectName; }
            set { _projectName = value; }
        }
        public String Url
        {
            get { return _url; }
            set 
            {
                _url = value;
                OutputFilePath = ParseURLDir(value);
            }
        }
        public String OutputFilePath
        {
            get { return _outputfilepath; }
            set { _outputfilepath = value; }
        }
        public Double RuntimeMS
        {
            get { return _msRuntime; }
            set { _msRuntime = value; }
        }
        public DateTime StartTime
        {
            get { return _StartTime; }
            set { _StartTime = value; }
        }
        public DateTime EndTime
        {
            get { return _EndTime; }
            set { _EndTime = value; }
        }
        public UrlProcessed UrlProcessed
        {
            get { return _urlProcessed; }
            set { _urlProcessed = value; }
        }
        public List<DirectoryList> FilesProcessed
        {
            get { return _filesProcessed; }
            set { _filesProcessed = value; }
        }

        internal UrlProcessing()
        {
        }
        public UrlProcessing (String project, String targetUrl, uint siteCount)
        {
            ProjectName = project;
            Url = targetUrl;
            SiteId = siteCount;
        }

        public void Start()
        {
            //System.Threading.Thread scanThread = new System.Threading.Thread(StartBackground);
            //scanThread.Priority = System.Threading.ThreadPriority.Lowest;
            //scanThread.Name = "UrlProcessing - " +  URL;
            //scanThread.Start();
            StartBackground();
        }

        private void StartBackground()
        {
            lock (thisLock)

                try
                {
                    StartTime = DateTime.Now;

                    if (CreateURLDir(OutputFilePath))
                    {
                        //Get website files
                        StartWGET(); 

                        //Parse files for Information
                        foreach (String s in System.IO.Directory.GetFiles(OutputFilePath, "*.*", SearchOption.AllDirectories))
                        {
                            try
                            {
                                FileInfo fileinfo = new FileInfo(s);
                                
                                if (!String.Equals(fileinfo.Name, "URL.TXT", StringComparison.OrdinalIgnoreCase))
                                {
                                    //MD5
                                    String md5hash = CalculateHash.GetMD5HashFromFile(fileinfo.FullName);

                                    //FILE TYPE
                                    String fileID = FileID.ScanFile(s);

                                    //MISMATCH
                                    Boolean extMisMatch = FileConfig.ExtensionMisMatch(fileinfo.Extension, fileID);

                                    DirectoryList dirlist = new DirectoryList(SiteId, Url, fileinfo.Name, fileinfo.Extension, fileinfo.FullName, fileID, fileinfo.Length, md5hash, extMisMatch, false, "", "");
                                    FilesProcessed.Add(dirlist);
                                }
                            }
                            catch (Exception ex)
                            {
                                AlertOnEvent.OnAlertEvent(null, new AlertOnEventArgs(AlertOnEventArgs.MsgType.Error, "UrlProcessing", _url, ex.Message));
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    AlertOnEvent.OnAlertEvent(null, new AlertOnEventArgs(AlertOnEventArgs.MsgType.Error, "UrlProcessing", _url, ex.Message));
                }
                finally
                {
                    EndTime = DateTime.Now;
                    UrlProcessed = new UrlProcessed(SiteId, false, Url, DateTime.Now, OutputFilePath);
                }
        }

        private Boolean CreateURLDir(String Path)
        {
            Boolean created = false;

            try
            {
                if (!System.IO.Directory.Exists(Path))
                {
                    DirectoryInfo di = System.IO.Directory.CreateDirectory(Path);
                    created = di.Exists;
                }
                else
                {
                    created = true;
                }
               
            }
            catch (Exception ex)
            {
                AlertOnEvent.OnAlertEvent(null, new AlertOnEventArgs(AlertOnEventArgs.MsgType.Error, "Create Directory", _url, ex.Message));
            }

            return created;

        }

        private String ParseURLDir(String URL)
        {
            string value = String.Empty;

            try
            {

                //Create URL directory, characters are reserved and not allowed  \/:*?"<>|  replace with #.
                String urlDir = URL;
                urlDir = urlDir.Replace('\\', '#');
                urlDir = urlDir.Replace('/', '#');
                urlDir = urlDir.Replace(':', '#');
                urlDir = urlDir.Replace('*', '#');
                urlDir = urlDir.Replace('?', '#');
                urlDir = urlDir.Replace('<', '#');
                urlDir = urlDir.Replace('>', '#');
                urlDir = urlDir.Replace('|', '#');

                value = String.Format("{0}\\{1}\\{2}", ApplicationDirectory, ProjectName, urlDir);
            }
            catch (Exception ex)
            {
                AlertOnEvent.OnAlertEvent(null, new AlertOnEventArgs(AlertOnEventArgs.MsgType.Error, "Parse Url Directory", _url, ex.Message));
            }

            return value;
        }

        private void StartWGET()
        {
            try
            {

                //Get WGET filepath
                string FileName = ApplicationDirectory + "\\Dependencies\\" + "wget.exe";

                string arguments = String.Empty;

                //Get WGET arguments
                try
                {
                    arguments = Properties.Settings.Default.WGET;
                }
                catch (Exception ex)
                {
                    AlertOnEvent.OnAlertEvent(null, new AlertOnEventArgs(AlertOnEventArgs.MsgType.Error, "WGET Settings Not Found", _url, ex.Message));
                    arguments = "-t 1 -T 10 -nc --no-check-certificate --recursive --level=1 -p";
                }


                if (File.Exists(FileName))
                {
                    using (Execute exec = new Execute())
                    {

                        String Arguments = String.Format("{0} {1}", arguments, Url);
                        exec.RunWithTimer(FileName, Arguments, OutputFilePath, WindowStyle.Hidden, RuntimeMS);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("WGET.EXE not found @ " + FileName);
                    throw new FileNotFoundException("WGET.EXE not found @ " + FileName);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                throw;
            }
        }

    }
}
